using UnityEngine;
using UnityEditor;

[System.Serializable]
public class Bezier : System.Object
{
	#region Variables
	
	protected	Vector3 		p0;
//	private		Vector3 		p1;
//	private		Vector3 		p2;
//	private		Vector3 		p3;

	private 	float 			Ax;
	private 	float 			Ay;
	private 	float 			Az;

	private 	float 			Bx;
	private 	float 			By;
	private 	float 			Bz;

	private 	float 			Cx;
	private 	float			Cy;
	private 	float 			Cz;
	
	protected	float 			m_fLength; 
	
	public		int 			m_iLengthNumSteps = 50;
	
	#endregion
	
	#region Propertys
	
	public float Length
	{
		get{
			return m_fLength;
		}
	}
	
	#endregion

	//---------------------------------------------------------------------------------------------------------
	// handle1 = vOrigin + vOriginHandle
	// handle2 = vEnd + vEndHandle
	//---------------------------------------------------------------------------------------------------------
	public Bezier( Vector3 _vOrigin, Vector3 _vOriginHandle, Vector3 _vEndHandle, Vector3 _vEnd)
	{
		p0 					= _vOrigin;
		
		SetConstant(_vOriginHandle, _vEndHandle, _vEnd);
	}
	

	//---------------------------------------------------------------------------------------------------------
	// handle1 = vOrigin + vOriginHandle
	// handle2 = vEnd + vEndHandle
	//---------------------------------------------------------------------------------------------------------
	public void ChangeValues( Vector3 _vOrigin, Vector3 _vOriginHandle, Vector3 _vEndHandle, Vector3 _vEnd)
	{
		p0 					= _vOrigin;
		
		SetConstant(_vOriginHandle, _vEndHandle, _vEnd);
	}

	//---------------------------------------------------------------------------------------------------------
	// 0.0 >= t <= 1.0
	//---------------------------------------------------------------------------------------------------------
	public virtual Vector3 GetPointAtTime( float t)
	{
		float t2 = t * t;
		float t3 = t2 * t;
		Vector3 vPoint;
		vPoint.x = Ax * t3 + Bx * t2 + Cx * t + p0.x;
		vPoint.y = Ay * t3 + By * t2 + Cy * t + p0.y;
		vPoint.z = Az * t3 + Bz * t2 + Cz * t + p0.z;
		return vPoint;
	}

	
	//---------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------
	private void SetConstant(Vector3 p1, Vector3 p2, Vector3 p3)
	{
		Cx = 3f * ( ( p0.x + p1.x ) - p0.x );
		Bx = 3f * ( ( p3.x + p2.x ) - ( p0.x + p1.x ) ) - Cx;
		Ax = p3.x - p0.x - Cx - Bx;

		Cy = 3f * ( ( p0.y + p1.y ) - p0.y );
		By = 3f * ( ( p3.y + p2.y ) - ( p0.y + p1.y ) ) - Cy;
		Ay = p3.y - p0.y - Cy - By;

		Cz = 3f * ( ( p0.z + p1.z ) - p0.z );
		Bz = 3f * ( ( p3.z + p2.z ) - ( p0.z + p1.z ) ) - Cz;
		Az = p3.z - p0.z - Cz - Bz;
		
		
		CalculateLength();
	}
	
	//---------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------
	protected virtual void CalculateLength()
	{
		m_fLength 	= 0;
		Vector3 	vPrev;
		Vector3 	vCur;
		vPrev		= this.p0;
		for (int i = 1; i < m_iLengthNumSteps; ++i)
		{
			vCur  		=	GetPointAtTime((float) i / (float) m_iLengthNumSteps);
			m_fLength 	+=	Vector3.Distance(vPrev, vCur);
			vPrev 		=	vCur;
		}
	}
	
	//---------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------
	public void DrawLined()
	{
		Vector3 vPrev;
		Vector3 vCur;
		vPrev = this.p0;
		for (int i = 1; i <= m_iLengthNumSteps; ++i)
		{
			vCur  = GetPointAtTime((float) i / (float) m_iLengthNumSteps);
			Debug.DrawLine(vPrev, vCur, Color.red); 
			vPrev = vCur;
		}
	}
}